#!/bin/bash
# Description: Linux Bonding交互式配置脚本
# Author: ddiplus
# Version: 2.0
# Date: 2025-03-26

set -eo pipefail

# 日志输出颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'

# 默认配置参数
DEFAULT_BOND_NAME="bond0"
DEFAULT_BOND_MODE="4"
DEFAULT_SLAVES=("eth0" "eth1")
DEFAULT_IP="192.168.1.100/24"
DEFAULT_GW="192.168.1.1"
DEFAULT_DNS=("8.8.8.8" "8.8.4.4")

# 初始化变量
CONFIG_FILE="/tmp/bonding_config_$(date +%s).conf"
LOG_FILE="/var/log/bonding_setup.log"

# 日志记录函数
log() {
    local level=$1
    local message=$2
    local timestamp=$(date +"%Y-%m-%d %T")
    echo -e "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
}

# 带默认值的输入函数
input_with_default() {
    local prompt=$1
    local default=$2
    read -p "${prompt} [默认: ${default}]: " input
    echo "${input:-$default}"
}

# 参数收集函数
collect_parameters() {
    echo -e "${GREEN}=== 网络聚合配置向导 ===${NC}"
    
    BOND_NAME=$(input_with_default "请输入Bond接口名称" "$DEFAULT_BOND_NAME")
    BOND_MODE=$(input_with_default "选择Bond模式 (0-6)" "$DEFAULT_BOND_MODE")
    
    echo -e "\n${YELLOW}可用的网络接口：${NC}"
    ip -o link show | awk -F': ' '{print $2}' | grep -v lo
    read -p "输入从属网卡（空格分隔）[默认: ${DEFAULT_SLAVES[*]}]: " slaves_input
    SLAVE_NICS=(${slaves_input:-${DEFAULT_SLAVES[@]}})
    
    IP_ADDR=$(input_with_default "设置IP地址（CIDR格式）" "$DEFAULT_IP")
    GATEWAY=$(input_with_default "指定默认网关" "$DEFAULT_GW")
    
    read -p "输入DNS服务器（空格分隔）[默认: ${DEFAULT_DNS[*]}]: " dns_input
    DNS_SERVERS=(${dns_input:-${DEFAULT_DNS[@]}})
}

# 参数确认函数
confirm_parameters() {
    echo -e "\n${GREEN}=== 配置确认 ===${NC}"
    echo -e "Bond接口: ${YELLOW}${BOND_NAME}${NC}"
    echo -e "工作模式: ${YELLOW}mode ${BOND_MODE}${NC}"
    echo -e "从属网卡: ${YELLOW}${SLAVE_NICS[*]}${NC}"
    echo -e "IP地址  : ${YELLOW}${IP_ADDR}${NC}"
    echo -e "网关    : ${YELLOW}${GATEWAY}${NC}"
    echo -e "DNS     : ${YELLOW}${DNS_SERVERS[*]}${NC}"
    
    read -p "是否确认配置？(y/n) " -n 1 -r
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo -e "\n${RED}配置已取消${NC}"
        exit 0
    fi
    echo
}

# 参数校验函数
validate_params() {
    # 必须使用root权限
    if [[ $EUID -ne 0 ]]; then
        log "ERROR" "必须使用root权限运行此脚本"
        exit 1
    fi

    # 检查必要工具
    for cmd in ip ethtool grep awk; do
        if ! command -v $cmd &> /dev/null; then
            log "ERROR" "缺少必要工具: $cmd"
            exit 1
        fi
    done

    # 验证bond模式有效性
    local valid_modes=(0 1 2 3 4 5 6)
    if [[ ! " ${valid_modes[@]} " =~ " ${BOND_MODE} " ]]; then
        log "ERROR" "无效的bond模式: ${BOND_MODE}"
        exit 1
    fi

    # 验证网卡存在性
    for nic in "${SLAVE_NICS[@]}"; do
        if ! ip link show "$nic" &> /dev/null; then
            log "ERROR" "网卡 ${nic} 不存在"
            exit 1
        fi
    done
}

# 生成配置文件（多发行版兼容）
generate_config() {
    log "INFO" "生成网络配置文件..."
    
    if [[ -d /etc/sysconfig/network-scripts ]]; then  # CentOS/RHEL
        # Bond接口配置
        cat > /etc/sysconfig/network-scripts/ifcfg-${BOND_NAME} <<EOF
DEVICE=${BOND_NAME}
TYPE=Bond
NAME=${BOND_NAME}
BONDING_MASTER=yes
BONDING_OPTS="mode=${BOND_MODE} miimon=100"
IPADDR=${IP_ADDR%/*}
PREFIX=${IP_ADDR#*/}
GATEWAY=${GATEWAY}
DNS1=${DNS_SERVERS[0]}
DNS2=${DNS_SERVERS[1]}
ONBOOT=yes
NM_CONTROLLED=no
EOF

        # 从接口配置
        for nic in "${SLAVE_NICS[@]}"; do
            cat > /etc/sysconfig/network-scripts/ifcfg-${nic} <<EOF
DEVICE=${nic}
NAME=${nic}
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
MASTER=${BOND_NAME}
SLAVE=yes
NM_CONTROLLED=no
EOF
        done

    elif [[ -d /etc/netplan ]]; then  # Ubuntu
        local netplan_file="/etc/netplan/99-bonding.yaml"
        cat > ${netplan_file} <<EOF
network:
  version: 2
  renderer: networkd
  bonds:
    ${BOND_NAME}:
      interfaces: [$(IFS=,; echo "${SLAVE_NICS[*]}")]
      parameters:
        mode: ${BOND_MODE}
        mii-monitor-interval: 100
      addresses: [${IP_ADDR}]
      routes:
        - to: default
          via: ${GATEWAY}
      nameservers:
        addresses: [$(IFS=,; echo "${DNS_SERVERS[*]}")]
EOF

    else
        log "ERROR" "不支持的Linux发行版"
        exit 1
    fi
}

# 应用配置
apply_config() {
    log "INFO" "加载bonding内核模块..."
    modprobe bonding || {
        log "ERROR" "无法加载bonding模块"
        exit 1
    }

    log "INFO" "重启网络服务..."
    if systemctl is-active NetworkManager &> /dev/null; then
        systemctl stop NetworkManager
    fi

    if [[ -d /etc/sysconfig/network-scripts ]]; then
        systemctl restart network
    elif [[ -d /etc/netplan ]]; then
        netplan apply
    else
        log "ERROR" "无法确定网络服务类型"
        exit 1
    fi

    sleep 3  # 等待服务稳定
}

# 配置验证
verify_config() {
    log "INFO" "验证bonding状态..."
    
    # 检查bond接口是否存在
    if ! ip link show ${BOND_NAME} &> /dev/null; then
        log "ERROR" "Bond接口 ${BOND_NAME} 创建失败"
        exit 1
    fi

    # 检查从接口状态
    local bond_status=$(cat /proc/net/bonding/${BOND_NAME})
    for nic in "${SLAVE_NICS[@]}"; do
        if ! grep -q "Slave Interface: ${nic}" <<< "$bond_status"; then
            log "ERROR" "从接口 ${nic} 未成功加入bond"
            exit 1
        fi
    done

    # 检查网络连通性
    if ! ping -c 3 -I ${BOND_NAME} ${GATEWAY} &> /dev/null; then
        log "ERROR" "网络连通性测试失败"
        exit 1
    fi

    log "SUCCESS" "Bonding配置验证通过"
}

# 主执行流程
main() {
    collect_parameters
    confirm_parameters
    
    # 后续保持原有验证和配置逻辑
    validate_params  # 需要确保此函数已包含参数验证
    generate_config
    apply_config
    verify_config
}


main